import json
from django.db import models, transaction


class ActiveBaseModel(models.Model):  # 基类
    active = models.SmallIntegerField(verbose_name='状态', default=1, choices=(('1', '激活'), ('0', '删除')))

    class Meta:
        abstract = True  # 这样就不会在数据库里生成ActiveBaseModel这个表了,只为子类提供公共的字段


class AdminCustomer(ActiveBaseModel):  # 继承基类，这样就有active这个字段了
    """ 管理员 和 用户 公用一张表 """
    username = models.CharField(verbose_name="用户名", max_length=32, db_index=True)
    password = models.CharField(verbose_name="密码", max_length=64)
    mobile = models.CharField(verbose_name="手机号", max_length=11, db_index=True)
    email = models.CharField(verbose_name='邮箱', max_length=32, db_index=True)
    picture = models.CharField(verbose_name='头像', max_length=32)
    create_date = models.DateTimeField(verbose_name="创建日期",
                                       auto_now_add=True)  # auto_now=True会随着以后的修改而更新未最新时间，而auto_now_add=True只是最早的时间，不会随着以后的修改而改变时间
    person_choices = ((1, "用户"), (2, "管理员"),)
    person = models.SmallIntegerField(verbose_name="人员分类", choices=person_choices, default=1)

    #  以后取值
    # data = AdminCustomer.objects.all()
    # for item in data:
    #     item.username
    #     item.active  # 0/1
    #     item.get_active_display() # 取到中文的： “激活”或者“删除”

    def __str__(self):
        return self.username + ': ' + self.email


class Platform(models.Model):
    """ 平台表 """
    name = models.CharField(verbose_name="平台名称", max_length=32)
    accessKey = models.CharField(verbose_name="平台Key", max_length=32)
    accessSecret = models.CharField(verbose_name="平台secret", max_length=32)
    # 关联用户表(多对一)
    toAdmin = models.ForeignKey('AdminCustomer', on_delete=models.CASCADE, verbose_name='用户')

    # toPlat = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children', verbose_name='平台选择')

    def __str__(self):
        return self.name


class Example(models.Model):
    """ 实例表 """
    iotInstanceId = models.CharField(verbose_name="实例id", max_length=32)
    iotInstanceId_alias = models.CharField(verbose_name="实例别名", max_length=32)
    clientId = models.CharField(verbose_name="客户端ID", max_length=32)
    host_name = models.CharField(verbose_name="服务器所在地", max_length=32)
    consumerGroupId = models.CharField(verbose_name="消费组", max_length=32)
    # 关联平台表(多对一)
    toPlat = models.ForeignKey('Platform', on_delete=models.CASCADE)

    def __str__(self):
        return self.iotInstanceId


class Product(models.Model):
    """ 产品表 """
    product_key = models.CharField(verbose_name="产品ProductKey", max_length=32)
    product_key_alias = models.CharField(verbose_name="产品别名", max_length=32)
    # 关联实例表(多对一)
    toExample = models.ForeignKey('Example', on_delete=models.CASCADE)

    def __str__(self):
        return self.product_key


class FunDefine(models.Model):
    funcName = models.CharField(verbose_name="功能名称", max_length=32)
    funcType = models.CharField(verbose_name="功能类型", max_length=32, default='属性')  # 有属性 服务 事件，这里默认“属性”，可以不在页面显示
    Identifier = models.CharField(verbose_name="标识符", max_length=32)
    CHOICES = (
        (1, 'int32(整数型)'),
        (2, 'float (单精度浮点型)'),
        (3, 'double (双精度浮点型)'),
        (4, 'enum(枚举类)'),
        (5, 'bool(布尔型)'),
        (6, 'text(字符串)'),
        (7, 'date(时间型)'),
        (8, 'struct(结构体)'),
        (9, 'array(数组)')
    )
    dataType = models.IntegerField(verbose_name="数据类型", choices=CHOICES)
    dataDefine = models.CharField(verbose_name="数据定义", max_length=64)  # 作为dataType和min，max，step，unit的说明
    min = models.FloatField(verbose_name="最小值")
    max = models.FloatField(verbose_name="最大值")
    step = models.FloatField(verbose_name="步长")
    CHOICES_unit = (
        (1, '无/'),
        (2, '升每分钟/L/min'),
        (3, '毫克每千克/mg/kg'),
        (4, '浊度/NTU'),
        (5, 'PH值/pH'),
        (6, '土壤EC值/ds/m'),
        (7, '太阳总辐射/w/㎡'),
        (8, '降雨量/mm/hour'),
        (9, '乏/var'),
        (10, '厘泊/cP'),
        (11, '饱和度/aw'),
        (12, '个/pcs'),
        (13, '厘斯/cst'),
        (14, '巴/bar'),
        (15, '纳克每升/ppt'),
        (16, '微克每升/ppb'),
        (17, '微西每厘米/us/cm'),
        (18, '牛顿每库仑/N/C'),
        (19, '伏特每米/V/m'),
        (20, '滴速/ml/min'),
        (21, '毫米汞柱/mmHg'),
        (22, '血糖/mmol/L'),
        (23, '毫米每秒/mm/s'),
        (24, '次/count'),
        (25, '档/gear'),
        (26, '步/stepCount'),
        (27, '标准立方米每小时/Nm³/h'),
        (28, '千伏/kv'),
        (29, '千伏安/kVA'),
        (30, '千乏/kVar'),
        (31, '微瓦每平方厘米/uw/c㎡'),
        (32, '只/只'),
        (33, '相对湿度/%RH'),
        (34, '立方米每秒/m³/s'),
        (35, '公斤每秒/kg/s'),
        (36, '转每分钟/r/min'),
        (37, '吨每小时/t/h'),
        (38, '千卡每小时/KCL/h'),
        (39, '升每秒/L/s'),
        (40, '兆帕/Mpa'),
        (41, '立方米每小时/m³/h'),
        (42, '千乏时/kvarh'),
        (43, '微克每升/pg/L'),
        (44, '千卡路里/kcal'),
        (45, '吉字节/GB'),
        (46, '兆字节/MB'),
        (47, '千字节/KB'),
        (48, '字节/B'),
        (49, '微克每平方分米每天/μg/(dm·d)'),
        (50, '百万分率/ppm'),
        (51, '像素/pixel'),
        (52, '照度/Lux'),
        (53, '重力加速度/grav'),
        (54, '分贝/dB'),
        (55, '百分比/%'),
        (56, '流明/lm'),
        (57, '比特/bit'),
        (58, '克每毫升/g/mL'),
        (59, '克每升/g/L'),
        (60, '毫克每升/mg/L'),
        (61, '微克每立方米/pg/m³'),
        (62, '毫克每立方米/mg/m³'),
        (63, '克每立方米/g/m³'),
        (64, '千克每立方米/kg/m³'),
        (65, '纳法/nF'),
        (66, '皮法/pF'),
        (67, '微法/μF'),
        (68, '法拉/F'),
        (69, '欧姆/Ω'),
        (70, '微安/μA'),
        (71, '毫安/mA'),
        (72, '千安/kA'),
        (73, '安培/A'),
        (74, '毫伏/mV'),
        (75, '伏特/V'),
        (76, '毫秒/ms'),
        (77, '秒/s'),
        (78, '分钟/min'),
        (79, '小时/h'),
        (80, '日/day'),
        (81, '周/week '),
        (82, '月/month'),
        (83, '年/year'),
        (84, '节/kn'),
        (85, '千米每小时/km/h'),
        (86, '米每秒/m/s'),
        (87, "秒/''"),
        (88, "分/'"),
        (89, '度/°'),
        (90, '弧度/rad'),
        (91, '赫兹/HZ'),
        (92, '微瓦/μW'),
        (93, '毫瓦/mW'),
        (94, '千瓦特/kw'),
        (95, '瓦特/W'),
        (96, '卡路里/cal'),
        (97, '千瓦时/kw·h'),
        (98, '瓦时/wh'),
        (99, '电子伏/eV'),
        (100, '千焦/kJ'),
        (101, '焦耳/J'),
        (102, '华氏度/℉'),
        (103, '开尔文/K'),
        (104, '吨/t '),
        (105, '摄氏度/℃'),
        (106, '毫帕/mPa'),
        (107, '百帕/hPa'),
        (108, '千帕/kPa'),
        (109, '帕斯卡/Pa'),
        (110, '毫克/mg'),
        (111, '克/g'),
        (112, '千克/kg'),
        (113, '牛/N'),
        (114, '毫升/mL'),
        (115, '升/L'),
        (116, '立方毫米/mm³'),
        (117, '立方厘米/cm³'),
        (118, '立方千米/km³'),
        (119, '立方米/m³'),
        (120, '公顷/h㎡'),
        (121, '平方厘米/c㎡'),
        (122, '平方笔米/m㎡'),
        (123, '平方千米/k㎡'),
        (124, '平方米/㎡'),
        (125, '纳米/nm'),
        (126, '微米/μm'),
        (127, '毫米/mm'),
        (128, '厘米/cm'),
        (129, '分米/dm'),
        (130, '千米/km'),
        (131, '米/m'),
    )
    unit = models.IntegerField(verbose_name="单位符号", choices=CHOICES_unit)
    value = models.CharField(verbose_name="值", max_length=32)
    # 关联产品表(多对一)
    toProductFuc = models.ForeignKey('Product', on_delete=models.CASCADE)


class Device(models.Model):
    """ 设备表 """
    device_name = models.CharField(verbose_name="设备名DeviceName", max_length=32)
    device_name_alias = models.CharField(verbose_name="设备别名", max_length=32)
    device_secret = models.CharField(verbose_name="设备DeviceSecret", max_length=32)
    # 关联产品表(多对一)
    toProduct = models.ForeignKey('Product', on_delete=models.CASCADE)

    def __str__(self):
        return self.device_name


class DeviceData(models.Model):
    """ 设备数据表 """
    deviceType = models.CharField(verbose_name="设备类型", max_length=32)
    iotId = models.CharField(verbose_name="实例id", max_length=32)
    requestId = models.CharField(verbose_name="请求id", max_length=32)
    checkFailedData = models.CharField(verbose_name="失败数据", max_length=32)
    productKey = models.CharField(verbose_name="产品id", max_length=32)
    # gmtCreate = models.TimeField(verbose_name="创建时间")
    gmtCreate = models.CharField(verbose_name="创建时间", max_length=64)
    deviceName = models.CharField(verbose_name="设备名称", max_length=32)
    items = models.TextField(verbose_name="返回值")
    # items = models.JSONField(verbose_name="返回值", default=dict)  # 替换原TextFi
    sendOrReceive = models.IntegerField(verbose_name='发送/接收', default=0)  # 0接收成功 1上报成功 2发送失败
    version = models.PositiveIntegerField(default=1, verbose_name="数据版本")  # 新增字段
    # 关联设备表(多对一)
    toDevice = models.ForeignKey('Device', on_delete=models.CASCADE)

    def save(self, *args, **kwargs):
        """原子化版本更新"""
        from django.db import transaction
        from django.db.models import F, Max

        with transaction.atomic():
            if self.pk is not None:  # 更新现有对象
                DeviceData.objects.filter(pk=self.pk).update(version=F('version') + 1)
                self.version = DeviceData.objects.get(pk=self.pk).version
            else:  # 新对象
                # 获取当前最大版本号并+1
                max_version = DeviceData.objects.aggregate(max_v=Max('version'))['max_v'] or 0
                self.version = max_version + 1
            super().save(*args, **kwargs)

    def get_parsed_items(self):
        """解析items为字典"""
        try:
            return json.loads(self.items)
        except:
            return {}

    class Meta:
        indexes = [
            models.Index(fields=['deviceName', 'productKey', 'sendOrReceive']),
            models.Index(fields=['gmtCreate']),  # 确保时间字段有索引
        ]
        verbose_name = '设备数据'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.deviceType

    # def __str__(self):
    #     # 获取模型所有字段的字典
    #     from django.forms.models import model_to_dict
    #     data = model_to_dict(self)
    #     # 转换为易读格式
    #     return "DeviceData(" + ", ".join(f"{k}={v}" for k, v in data.items()) + ")"
